JSONにルールをチョイ足しして実行できるJSON拡張記法 SushiJSON
概要
JSON自体はそのままだと値にしかならないが、
JSONに外部文字列を与えて、単純なパーサーで実行できるようにした。
その定義とパーサーとサンプルの実行実装をまとめたものがこれ。
https://github.com/sassembla/SushiJSON
できること
・JSONの外側に文字列を追加するだけで形成可能
・自分用のAPIを定義して実行できる
・APIから別のAPIの実行が可能
なので、JSONをデータとして受取って動作する機構があった時、
・受取ったデータから特定のパラメータを取り出して動作する
みたいなのが、
・受取ったデータを元にダイレクトに動作する
という形にできる。危ない。
使用例
SublimeSocket3
https://github.com/sassembla/SublimeSocket3
Sublime Text のAPIを、この記法でWebSocket越しに実行できるようにした。
対応するSTのAPIを書き、順などを指定して遠隔実行したり、内部にフィルタなどを構築できる。
ST2用のSublimeSocketにマージ中。
記法サンプル
ファイルか、ネットワーク経由のデータで下記みたいな記法のものを送り込み
helloworld.txt or data via network
helloWorld: {←最外部はquote無し、:付き。 :以降はJSON。
"message": "hello world!"
}
実装サンプル
こんなかんじの実装を書く事で
data = ファイルデータ
def runAPI(command, params):
# print "message" value
if command == "helloWorld":
assert "message" in params, "helloWorld requires 'message' param."
print(params["message"])
// run
[runAPI(command, params) for command, params in SushiJSONParser.parseFromFile(data)]
実行結果サンプル
動作、結果がでる。
hello world!
特徴とか
JSONをAPIへのパラメータとして使用する
APIName:{JSON}
APIName: {
"key": "value"
}
APIName: から先がJSON。
JSONとして解釈できさえすればOKなので、
APIName: {
"keys": [
"key1",
"key2",
"key3"
],
"values": {
"key1": "value1",
"key2": "value2",
"key3": "value3"
},
"something": [
{
"key": "value",
"array": [
"key1",
100,
false
]
}
]
}
など、配列入れたり辞書いれたり値入れたり、自由にできる。
まあこんな引数で動作するAPI厭だが。
順解釈して実行可
parserからだと、 -> で接続したAPIを順に解釈して実行できる。
単純な順実行で、値の共有などは無し。
APIName: {
"key": "value"
}
->APIName2: {
"key2": "value2"
}
ネスト可
APIの実行後、内部から次のAPIを実行する機構として、"selectors"キーワードを使用する。
selectorsの中身は順番で実行されるが、同一selectors内にあるAPI間の値の引き渡しは無し。
APIName1: {
"key1": "value1"
"selectors": [
{
"APIName2": {
"key2": "value2"
}
},
{
"APIName3": {
"key3":"value3"
}
}
]
}
API間の値の受け渡しに対してグローバル無し+明示的
selectorsを介して実行するAPIのパラメータ部分へと、キーを指定してキー+値の代入ができる。
代入するキーを明示しないと代入されない。
APIName1: {
"selectors": [
{
"APIName2<-APIName1の結果のキー": {
// + APIName1の結果のキー: APIName1の結果
}
}
]
}
処理系実装がどの言語でもたぶん簡単
処理系はJSONのSerialize/Deserializeが用意されてる言語なら200行くらいで実装できるはず。
ジェネレータがあれば逐次実行も容易。
Pythonでの処理系はこんな感じ。
https://github.com/sassembla/SushiJSON/blob/master/parser/SushiJSON.py
動作系の実装がどの言語でも割と簡単
パースとAPIのネスト実行まで含めてこんなかんじに書ける。
https://github.com/sassembla/SushiJSON/blob/master/parser/runtimeSample/SampleSushiJSONRunner.py#L18